package cd.cdyb.sms.listener;

import cd.cdyb.sms.dto.MessageCarrier;
import cd.cdyb.sms.dto.expand.ExCompanyDto;
import cd.cdyb.sms.service.*;
import cd.cdyb.sms.utils.JacksonUtilPlus;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author: lilin
 * @CreateTime: 2023-07-28  10:48
 * @Description: 队列监听
 */
@Slf4j
@Component
public class MessageRabbitListener {

    @Resource
    private InventoryService inventoryService;

    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    @Resource
    private SmsService smsService;

    @Resource
    private MessageRecordingService messageRecordingService;
    @Resource
    private TemplateService templateService;

    @Resource
    private CompanyService companyService;

    @Resource
    private RedisService redisService;

    @RabbitListener(queues = "${mq.message_queue}")
    public void listener(String obj, Channel channel) {
        sendMessage(obj);
    }

    @RabbitListener(queues = "${mq.message_queue}")
    public void listener2(String obj, Channel channel) {
        sendMessage(obj);
    }

    @RabbitListener(queues = "${mq.message_queue}")
    public void listener3(String obj, Channel channel) {
        sendMessage(obj);
    }

    @RabbitListener(queues = "${mq.message_queue}")
    public void listener4(String obj, Channel channel) {
        sendMessage(obj);
    }

    @RabbitListener(queues = "${mq.message_queue}")
    public void listener5(String obj, Channel channel) {
        sendMessage(obj);
    }

    private void sendMessage(String message) {
        MessageCarrier messageCarrier = JacksonUtilPlus.readValue(message, MessageCarrier.class);
        String phone = messageCarrier.getPhone();
        boolean whetherLimitSend = whetherLimitSend(messageCarrier.getCompanyKey(), phone);
        if (whetherLimitSend) {
            return;
        }
        List<String> params = messageCarrier.getParams();
        String connect = "";
        if (!CollectionUtils.isEmpty(params)) {
            connect = params.stream().collect(Collectors.joining(","));
        }
        String templateId = messageCarrier.getTemplateId();
        String content = templateService.getCacheTemplateById(templateId);
        if (!CollectionUtils.isEmpty(params)) {
            for (int i = 1; i <= params.size(); i++) {
                String name = "{{var" + i + "}}";
                content = content.replace(name, params.get(i - 1));
            }
        }
        int length = content.length();
        int useCount = length / 70 + 1;
        messageCarrier.setContent(content);
        messageCarrier.setUseCount(useCount);
        //先减库存, 后续再通过失败记录加回来
        Boolean isReduce = inventoryService.reduceInventory(messageCarrier.getCompanyKey(), useCount, messageCarrier.getType());
        if (isReduce) {
            //发送短信
            Map<String, String> result = smsService.sendMessage(messageCarrier.getPhone(), messageCarrier.getTemplateId(), connect, messageCarrier.getType());
            String isSucess = result.get("isSucess");
            if ("true".equals(isSucess)) {
                String no = result.get("no");

                messageCarrier.setTaskNo(no);
                //新增消息记录
                messageRecordingService.insertMessageRecording(messageCarrier);
            } else {
                String desc = result.get("desc");
                if (StringUtils.isEmpty(desc)){
                    messageCarrier.setFailReason("未返回失败原因");
                } else {
                    messageCarrier.setFailReason(desc);
                }
                //新增消息记录
                messageRecordingService.insertMessageRecording(messageCarrier);
            }
        } else {
            messageCarrier.setFailReason("库存不足");
            //新增消息记录
            messageRecordingService.insertMessageRecording(messageCarrier);
        }

    }

    private boolean whetherLimitSend(String companyKey, String phone) {
        LocalDate today = LocalDate.now();
        String dayFormat = today.format(DATE_FORMATTER);
        Integer dayCount = (Integer) redisService.vGet(dayFormat + ":" + phone);
        if (dayCount == null) {
            //增加每日次数
            redisService.vPut(dayFormat + ":" + phone, 1, 60 * 60 * 24);

            //缓存每小时次数
            redisService.vPut("HOUR_LIMIT:" + phone, 1, 60 * 60);

            //缓存每分钟次数
            redisService.vPut("MINUTE_LIMIT:" + phone, 1, 60);

        } else {
            ExCompanyDto cacheCompanyByKey = companyService.getCacheCompanyByKey(companyKey);
            Integer dayLimit = cacheCompanyByKey.getDayLimit();
            if (dayLimit <= dayCount) {
                return true;
            }

            Integer hourCount = (Integer) redisService.vGet("HOUR_LIMIT:" + phone);
            if (hourCount == null){
                hourCount = 0;
            }
            Integer hourLimit = cacheCompanyByKey.getHourLimit();
            if (hourLimit <= hourCount) {
                return true;
            }

            Integer minuteCount = (Integer) redisService.vGet("MINUTE_LIMIT:" + phone);
            if (minuteCount == null){
                minuteCount = 0;
            }
            Integer minuteLimit = cacheCompanyByKey.getMinuteLimit();
            if (minuteLimit <= minuteCount) {
                return true;
            }

            redisService.vIncrement(dayFormat + ":" + phone, 1L);
            redisService.vIncrement("HOUR_LIMIT:" + phone, 1L);
            redisService.vIncrement("MINUTE_LIMIT:" + phone, 1L);
        }
        return false;

    }
}
